#ifndef __ACCEPTOR_HPP__
#define __ACCEPTOR_HPP__

class Acceptor
{
    using AcceptCallback = std::function<void(int)>;

private:
    /* 监听套接字上可读事件被触发后的回调函数——获取新连接，调用AcceptCallback回调函数进行新连接处理 */
    void HandleRead()
    {
        // 获取新连接
        int newfd = _socket.Accept();
        if (newfd < 0)
            return;
        // 调用新连接获取成功的回调函数，处理新连接
        if (_accept_callback)
            _accept_callback(newfd);
    }
    /* 创建服务器连接，获得一个合法的文件描述符 */
    int CreateServer(int port)
    {
        Socket sock;
        assert(sock.CreateServer(port));
        _socket.Swap(sock);
        return _socket.Fd();
    }

public:
    Acceptor(EventLoop *loop, int port) : _socket(CreateServer(port)), _loop(loop), _channel(_socket.Fd(), _loop)
    {
        // 1. 创建服务器连接——监听套接字
        // 2. 设置监听套接字的可读事件回调，启动读事件监控
        _channel.SetReadCallback(std::bind(&Acceptor::HandleRead, this));
        // _channel.EnableRead(); 
        /* 不能将启动读事件监控放到构造函数中，因为构造函数中启动读事件监控后，可能就立即有读事件就绪获取了，
        就成功获取新连接，但是此时新连接获取成功的回调还没有设置，就什么都不做，导致新连接得不到处理，且产生内存泄漏。
        所以必须在设置完新连接获取成功的回调函数后启动读事件监控 */
    }
    /* 设置新连接获取成功的回调函数 */
    void SetAcceptCallback(const AcceptCallback &cb)
    {
        _accept_callback = cb;
    }
    /* 启动监听套接字上的读事件监控 */
    void Listen()
    {
        _channel.EnableRead();
    }

private:
    Socket _socket;   // 用于创建监听套接字
    EventLoop *_loop; // 用于对监听套接字进行事件监控
    Channel _channel; // 用于对监听套接字进行监控事件的管理

    AcceptCallback _accept_callback; // 获取新连接成功的回调函数
};

#endif